home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Programming / QuakeTools / src / libqbuild / writebsp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  15.4 KB  |  585 lines

  1. #define    LIBQBUILD_CORE
  2. #include "../include/libqbuild.h"
  3.  
  4. int headclipnode;            // 4
  5. int firstface;                // 4
  6.  
  7. /* changed by niels */
  8. int *planemapping;
  9.  
  10. //===========================================================================
  11.  
  12. /*
  13.  * ==================
  14.  * FindFinalPlane
  15.  * 
  16.  * Used to find plane index numbers for clip nodes read from child processes
  17.  * ==================
  18.  */
  19. int FindFinalPlane(__memBase, struct dplane_t * p)
  20. {
  21.   int i;
  22.   struct dplane_t *dplane;
  23.  
  24.   for (i = 0, dplane = bspMem->dplanes; i < bspMem->numplanes; i++, dplane++) {
  25.     if (p->type != dplane->type)
  26.       continue;
  27.     if (p->dist != dplane->dist)
  28.       continue;
  29.     if (p->normal[0] != dplane->normal[0])
  30.       continue;
  31.     if (p->normal[1] != dplane->normal[1])
  32.       continue;
  33.     if (p->normal[2] != dplane->normal[2])
  34.       continue;
  35.     return i;
  36.   }
  37.  
  38. //
  39.   // new plane
  40.   //
  41.   if (bspMem->numplanes == bspMem->max_numplanes)
  42.     ExpandClusters(bspMem, LUMP_PLANES);
  43.   dplane = &bspMem->dplanes[bspMem->numplanes];
  44.   *dplane = *p;
  45.   bspMem->numplanes++;
  46.  
  47.   return bspMem->numplanes - 1;
  48. }
  49.  
  50. void WriteNodePlanes_r(__memBase, register struct node * node)
  51. {
  52.   struct plane *plane;
  53.   struct dplane_t *dplane;
  54.  
  55.   if (node->planenum == -1)
  56.     return;
  57.   if (planemapping[node->planenum] == -1) {                       // a new plane
  58.  
  59.     planemapping[node->planenum] = bspMem->numplanes;
  60.  
  61.     if (bspMem->numplanes == bspMem->max_numplanes)
  62.       ExpandClusters(bspMem, LUMP_PLANES);
  63. #ifdef EXHAUSIVE_CHECK
  64.   if(node->planenum >= bspMem->numbrushplanes || node->planenum < 0)
  65.     Error("looking for nonexisting plane %d\n", node->planenum);
  66. #endif
  67.     plane = &bspMem->brushplanes[node->planenum];
  68.     dplane = &bspMem->dplanes[bspMem->numplanes];
  69.     dplane->normal[0] = plane->normal[0];
  70.     dplane->normal[1] = plane->normal[1];
  71.     dplane->normal[2] = plane->normal[2];
  72.     dplane->dist = plane->dist;
  73.     dplane->type = plane->type;
  74.  
  75.     bspMem->numplanes++;
  76.   }
  77.  
  78.   node->outputplanenum = planemapping[node->planenum];
  79.  
  80.   WriteNodePlanes_r(bspMem, node->children[0]);
  81.   WriteNodePlanes_r(bspMem, node->children[1]);
  82. }
  83.  
  84. /*
  85.  * ==================
  86.  * WriteNodePlanes
  87.  * 
  88.  * ==================
  89.  */
  90. void WriteNodePlanes(__memBase, struct node * nodes)
  91. {
  92.   /* added by niels -> probably not numbrushplanes */
  93.   if(!(planemapping = (int *)tmalloc(sizeof(int) * bspMem->numbrushplanes)))
  94.     Error("WriteNodePlanes: failed to allocate planemapping\n");
  95.   memset(planemapping, -1, sizeof(int) * bspMem->numbrushplanes);
  96.   WriteNodePlanes_r(bspMem, nodes);
  97.   /* added by niels */
  98.   tfree(planemapping);
  99. }
  100.  
  101. //===========================================================================
  102.  
  103. /*
  104.  * ==================
  105.  * WriteClipNodes_r
  106.  * 
  107.  * ==================
  108.  */
  109. int WriteClipNodes_r(__memBase, register struct node * node)
  110. {
  111.   int c;
  112.   short int i;
  113.   struct dclipnode_t *cn;
  114.   int num;
  115.  
  116. // FIXME: tfree more stuff?      
  117.   if (node->planenum == -1) {
  118.     num = node->contents;
  119.     tfree(node);
  120.     return num;
  121.   }
  122.  
  123.   if (bspMem->numclipnodes == bspMem->max_numclipnodes)
  124.     ExpandClusters(bspMem, LUMP_CLIPNODES);
  125. // emit a clipnode
  126.   c = bspMem->numclipnodes;
  127.   cn = &bspMem->dclipnodes[c];
  128.   bspMem->numclipnodes++;
  129.  
  130.   cn->planenum = node->outputplanenum;
  131.   for (i = 0; i < 2; i++)
  132.     cn->children[i] = WriteClipNodes_r(bspMem, node->children[i]);
  133.  
  134.   tfree(node);
  135.   return c;
  136. }
  137.  
  138. /*
  139.  * ==================
  140.  * WriteClipNodes
  141.  * 
  142.  * Called after the clipping hull is completed.  Generates a disk format
  143.  * representation and frees the original memory.
  144.  * ==================
  145.  */
  146. void WriteClipNodes(__memBase, struct node * nodes)
  147. {
  148.   headclipnode = bspMem->numclipnodes;
  149.   WriteClipNodes_r(bspMem, nodes);
  150. }
  151.  
  152. //===========================================================================
  153.  
  154. /*
  155.  * ==================
  156.  * WriteLeaf
  157.  * ==================
  158.  */
  159. void WriteLeaf(__memBase, register struct node * node)
  160. {
  161.   struct visfacet **fp, *f;
  162.   struct dleaf_t *leaf_p;
  163.  
  164. // emit a leaf
  165.   if (bspMem->numleafs == bspMem->max_numleafs)
  166.     ExpandClusters(bspMem, LUMP_LEAFS);
  167.   leaf_p = &bspMem->dleafs[bspMem->numleafs];
  168.   bspMem->numleafs++;
  169.  
  170.   leaf_p->contents = node->contents;
  171.  
  172. //
  173.   // write bounding box info
  174.   //      
  175.   VectorCopy(node->mins, leaf_p->mins);
  176.   VectorCopy(node->maxs, leaf_p->maxs);
  177.  
  178.   leaf_p->visofs = -1;                                   // no vis info yet
  179.  
  180. //
  181.   // write the marksurfaces
  182.   //
  183.   leaf_p->firstmarksurface = bspMem->nummarksurfaces;
  184.  
  185.   for (fp = node->markfaces; *fp; fp++) {
  186.     // emit a marksurface
  187.     f = *fp;
  188.     do {
  189.       if (bspMem->nummarksurfaces == bspMem->max_nummarksurfaces)
  190.         ExpandClusters(bspMem, LUMP_MARKSURFACES);
  191.       bspMem->dmarksurfaces[bspMem->nummarksurfaces] = f->outputnumber;
  192.       bspMem->nummarksurfaces++;
  193.       f = f->original;                                   // grab tjunction split faces
  194.     } while (f);
  195.   }
  196.  
  197.   leaf_p->nummarksurfaces = bspMem->nummarksurfaces - leaf_p->firstmarksurface;
  198. }
  199.  
  200. /*
  201.  * ==================
  202.  * WriteDrawNodes_r
  203.  * ==================
  204.  */
  205. void WriteDrawNodes_r(__memBase, register struct node * node)
  206. {
  207.   struct dnode_t *n;
  208.   short int i;
  209.  
  210. // emit a node  
  211.   if (bspMem->numnodes == bspMem->max_numnodes)
  212.     ExpandClusters(bspMem, LUMP_NODES);
  213.   n = &bspMem->dnodes[bspMem->numnodes];
  214.   bspMem->numnodes++;
  215.  
  216.   VectorCopy(node->mins, n->mins);
  217.   VectorCopy(node->maxs, n->maxs);
  218.  
  219.   n->planenum = node->outputplanenum;
  220.   n->firstface = node->firstface;
  221.   n->numfaces = node->numfaces;
  222.  
  223. //
  224.   // recursively output the other nodes
  225.   //      
  226.  
  227.   for (i = 0; i < 2; i++) {
  228.     if (node->children[i]->planenum == -1) {
  229.       if (node->children[i]->contents == CONTENTS_SOLID)
  230.     n->children[i] = -1;
  231.       else {
  232.     n->children[i] = -(bspMem->numleafs + 1);
  233.     WriteLeaf(bspMem, node->children[i]);
  234.       }
  235.     }
  236.     else {
  237.       n->children[i] = bspMem->numnodes;
  238.       WriteDrawNodes_r(bspMem, node->children[i]);
  239.     }
  240.   }
  241. }
  242.  
  243. /*
  244.  * ==================
  245.  * WriteDrawNodes
  246.  * ==================
  247.  */
  248. void WriteDrawNodes(__memBase, struct node * headnode)
  249. {
  250.   short int i;
  251.   int start;
  252.   struct dmodel_t *bm;
  253.  
  254. #if 0
  255.   if (headnode->contents < 0)
  256.     Error("FinishBSPModel: empty model");
  257. #endif
  258.  
  259. // emit a model
  260.   if (bspMem->nummodels == bspMem->max_nummodels)
  261.     ExpandClusters(bspMem, LUMP_MODELS);
  262.   bm = &bspMem->dmodels[bspMem->nummodels];
  263.   bspMem->nummodels++;
  264.  
  265.   bm->headnode[0] = bspMem->numnodes;
  266.   bm->firstface = firstface;
  267.   bm->numfaces = bspMem->numfaces - firstface;
  268.   firstface = bspMem->numfaces;
  269.  
  270.   start = bspMem->numleafs;
  271.  
  272.   if (headnode->contents < 0)
  273.     WriteLeaf(bspMem, headnode);
  274.   else
  275.     WriteDrawNodes_r(bspMem, headnode);
  276.   bm->visleafs = bspMem->numleafs - start;
  277.  
  278.   for (i = 0; i < 3; i++) {
  279.     bm->mins[i] = headnode->mins[i] + SIDESPACE + 1;                   // remove the padding
  280.     bm->maxs[i] = headnode->maxs[i] - SIDESPACE - 1;
  281.   }
  282. // FIXME: are all the children decendant of padded nodes?
  283. }
  284.  
  285. /*
  286.  * ==================
  287.  * BumpModel
  288.  * 
  289.  * Used by the clipping hull processes that only need to store headclipnode
  290.  * ==================
  291.  */
  292. void BumpModel(__memBase, int hullnum)
  293. {
  294.   struct dmodel_t *bm;
  295.  
  296. // emit a model
  297.   if (bspMem->nummodels == bspMem->max_nummodels)
  298.     ExpandClusters(bspMem, LUMP_MODELS);
  299.   bm = &bspMem->dmodels[bspMem->nummodels];
  300.   bspMem->nummodels++;
  301.  
  302.   bm->headnode[hullnum] = headclipnode;
  303. }
  304.  
  305. //=============================================================================
  306.  
  307. #define    MAX_MULTIPLE    32
  308.  
  309. /*
  310.  * ==================
  311.  * WriteMiptex
  312.  * ==================
  313.  */
  314. void WriteMiptex(__memBase)
  315. {
  316.   if(!(bspMem->bspOptions & QBSP_NOTEXTURES)) {
  317.     struct wadheader Header[MAX_MULTIPLE + 1];
  318.     struct wadentry *allEntries[MAX_MULTIPLE + 1];
  319.     char *wadPath[MAX_MULTIPLE + 1];
  320.     FILE *wadFile[MAX_MULTIPLE + 1];
  321.     int wadAvail = 0;
  322.     
  323.     char *dirPath[MAX_MULTIPLE + 1];
  324.     DIR *dirDir[MAX_MULTIPLE + 1];
  325.     int dirAvail = 0;
  326.     
  327.     /* TODO: multiple wadFiles */
  328.     wadPath[0] = ValueForKey(&bspMem->mapentities[0], "_wad");
  329.     if (!wadPath[0] || !wadPath[0][0])
  330.       wadPath[0] = ValueForKey(&bspMem->mapentities[0], "wad");
  331.     if (!wadPath[0] || !wadPath[0][0])
  332.       wadPath[0] = getenv("QUAKE_WADFILE");
  333.     
  334.     for(wadAvail = 0; wadAvail < MAX_MULTIPLE;) {
  335.       char *hit;
  336.       
  337.       if((hit = (char *)index(wadPath[wadAvail], ';')))    {    // cut off next entry
  338.         *hit = ' ';
  339.         while((hit[-1] == ' ') || (hit[-1] == '\t'))        // delete whitespace
  340.           hit--;
  341.         *hit++ = '\0';
  342.         while((*hit == ' ') || (*hit == '\t'))            // delete whitespace
  343.           hit++;
  344.       }
  345. #ifdef DEBUG
  346.       printf("wadPath %2d: \"%s\"\n", wadAvail, wadPath[wadAvail]);
  347. #endif
  348.       
  349.       if((wadPath[wadAvail][0]) && (wadFile[wadAvail] = fopen(wadPath[wadAvail], READ_BINARY))) {
  350.         if(CheckWAD2(wadFile[wadAvail], &Header[wadAvail], FALSE) == TRUE) {
  351.           FindWAD2(wadFile[wadAvail], 0, &Header[wadAvail], &allEntries[wadAvail], 0);
  352.           wadAvail++;
  353.         }
  354.         else {
  355.           fclose(wadFile[wadAvail]);
  356.           eprintf("file \"%s\" not a wad\n", wadPath[wadAvail]);
  357.         }
  358.       }
  359.       else
  360.         eprintf("wad \"%s\" not found\n", wadPath[wadAvail]);
  361.       
  362.       if(!hit)                            // break if nothing more found
  363.         break;
  364.       else
  365.         wadPath[wadAvail] = hit;                // register next entry
  366.     }
  367.     
  368.     /* TODO: multiple dirDirs */
  369.     dirPath[0] = ValueForKey(&bspMem->mapentities[0], "_dir");
  370.     if (!dirPath[0] || !dirPath[0][0])
  371.       dirPath[0] = ValueForKey(&bspMem->mapentities[0], "dir");
  372.     if (!dirPath[0] || !dirPath[0][0])
  373.       dirPath[0] = getenv("QUAKE_WADDIR");
  374.     if (!dirPath[0] || !dirPath[0][0])
  375.       dirPath[0] = "\0";
  376.     
  377.     for(dirAvail = 0; dirAvail < MAX_MULTIPLE;) {
  378.       char *hit;
  379.       
  380.       if((hit = (char *)index(dirPath[dirAvail], ';')))    {    // cut off next entry
  381.         *hit = ' ';
  382.         while((hit[-1] == ' ') || (hit[-1] == '\t'))        // delete whitespace
  383.           hit--;
  384.         *hit++ = '\0';
  385.         while((*hit == ' ') || (*hit == '\t'))            // delete whitespace
  386.           hit++;
  387.       }
  388. #ifdef DEBUG
  389.       printf("dirPath %2d: \"%s\"\n", dirAvail, dirPath[dirAvail]);
  390. #endif
  391.       
  392.       if((dirDir[dirAvail] = opendir(dirPath[dirAvail])))
  393.         dirAvail++;                        // skip unavailable entries
  394.       else
  395.         eprintf("dir \"%s\" is not a dir, or does not exists\n", dirPath[dirAvail]);
  396.       
  397.       if(!hit)                            // break if nothing more found
  398.         break;
  399.       else
  400.         dirPath[dirAvail] = hit;                // register next entry
  401.     }
  402. #ifdef DEBUG
  403.     printf("wads %2d, dirs %2d\n", wadAvail, dirAvail);
  404. #endif
  405.  
  406.     if(wadAvail || dirAvail) {
  407.       int i;
  408.       unsigned char *mipFlow;
  409.       struct dmiptexlump_t *mipBlock;
  410.       int texstrings = bspMem->nummaptexstrings;
  411.     
  412.       mipBlock = (struct dmiptexlump_t *) bspMem->dtexdata;
  413.       mipFlow = (unsigned char *) & mipBlock->dataofs[bspMem->nummaptexstrings];
  414.       mipBlock->nummiptex = bspMem->nummaptexstrings;
  415.       bspMem->texdatasize = mipFlow - bspMem->dtexdata;
  416.       
  417.       for (i = 0; i < texstrings; i++) {
  418.         struct rawdata *inPut;
  419.       
  420.         void GetInput(char *inName) {
  421.           int j;
  422.           struct wadentry *Entry;
  423.           
  424.           inPut = 0;
  425.         
  426.           /* first search in wadFiles */
  427.           for(j = 0; j < wadAvail; j++)
  428.             if((Entry = SearchWAD2(inName, &Header[j], allEntries[j], TYPE_MIPMAP)))
  429.               inPut = GetWAD2Raw(wadFile[j], Entry);
  430.         
  431.           /* if nothing found, search in dirDirs */
  432.           for(j = 0; (j < dirAvail) && !(inPut); j++) {
  433.         struct dirent *dirEnt = 0;
  434.  
  435.         while((dirEnt = readdir(dirDir[j]))) {
  436. #ifdef DEBUG
  437.               printf("dirname: %s wadname: %s\n", dirEnt->d_name, inName);
  438. #endif
  439.           if(!strncasecmp(dirEnt->d_name, inName, strlen(inName)))    // metal1 matches metal10*
  440.             if(dirEnt->d_name[strlen(inName)] == '.')        // metal1 matches metal1.*
  441.               break;
  442.         }
  443.       
  444.         if(dirEnt) {
  445.           char *fileExt = GetExt(dirEnt->d_name);
  446.           FILE *inFile;
  447.           struct palpic *inPic = 0;
  448.           char *fileName;
  449.         
  450.           if((fileName = (char *)tmalloc(NAMELEN_PATH + 1))) {
  451.             strncpy(fileName, dirPath[j], NAMELEN_PATH);
  452.             strncat(fileName, "/", NAMELEN_PATH);
  453.             strncat(fileName, dirEnt->d_name, NAMELEN_PATH);
  454.           
  455.             if((inFile = fopen(fileName, READ_BINARY))) {
  456.               if(!strcmp(fileExt, "mip"))
  457.                 inPut = GetRaw(inFile, inName, 0);
  458.               else if(!strcmp(fileExt, "lmp"))
  459.                 inPic = GetLMP(inFile, inName);
  460.               else {
  461.             short int alignX = 16, alignY = 16;
  462.       
  463.             if (fileName[0] == WARP_MIPMAP)
  464.               alignX = alignY = WARP_X;
  465.             else if (!strncasecmp(fileName, SKY_MIPMAP, 3)) {
  466.               alignX = -(SKY_X);
  467.               alignY = -(SKY_Y);
  468.             }
  469.             inPic = GetImage(inFile, inName, alignX, alignY);
  470.               }
  471.             
  472.               if(inPic) {
  473.                 if((inPut = rmalloc(MIP_MULT(inPic->width * inPic->height) + sizeof(struct mipmap), inName)))
  474.               PasteMipMap((struct mipmap *)inPut->rawdata, inPic);
  475.             pfree(inPic);
  476.               }
  477.               else
  478.                 eprintf("unknown fileformat %s\n", fileName);
  479.             
  480.               fclose(inFile);
  481.             }
  482.             else
  483.               eprintf("cannot open %s\n", fileName);
  484.             
  485.             tfree(fileName);
  486.           }
  487.         }
  488.       
  489.         rewinddir(dirDir[j]);
  490.           }
  491.         }
  492.         
  493.         void PutInput(char *inName) {
  494.           if(inPut) {
  495.             mipBlock->dataofs[i] = mipFlow - (unsigned char *)mipBlock;
  496.         mprintf("    - load texture %s\n", inPut->name);
  497.  
  498.             if ((bspMem->texdatasize + inPut->size) >= bspMem->max_texdatasize) {
  499.               ExpandClusters(bspMem, LUMP_TEXTURES);
  500.               mipBlock = (struct dmiptexlump_t *) bspMem->dtexdata;
  501.               mipFlow = bspMem->dtexdata + bspMem->texdatasize;
  502.             }
  503.             bspMem->texdatasize += inPut->size;
  504.         memcpy(mipFlow, inPut->rawdata, inPut->size);
  505.             mipFlow += inPut->size;
  506.             rfree(inPut);
  507.           }
  508.           else {
  509.             mipBlock->dataofs[i] = -1;
  510.             eprintf("texture %s not found!\n", inName);
  511.           }
  512.         }
  513.  
  514.         if (bspMem->maptexstrings[i][0] == '+') {
  515.           int j;
  516.           char name[20];
  517.         
  518.       strcpy(name, bspMem->maptexstrings[i]);
  519.  
  520.       for (j = 0; j < 20; j++) {
  521.         if (j < 10)
  522.           name[1] = '0' + j;
  523.         else
  524.           name[1] = 'A' + j - 10;                               // alternate animation
  525.  
  526.         GetInput(name);
  527.         // see if this name exists in the wadfile
  528.         if(inPut) {
  529.           PutInput(name);                                   // put only if it exists
  530.           //FindMiptex(bspMem, name);                           // add to the miptex list, if somebody after us needs it
  531.         }
  532.       }
  533.         }
  534.         else {
  535.           GetInput(bspMem->maptexstrings[i]);
  536.           PutInput(bspMem->maptexstrings[i]);
  537.         }
  538.       }
  539.       
  540.       for(i = 0; i < wadAvail; i ++)
  541.         fclose(wadFile[i]);
  542.       for(i = 0; i < dirAvail; i ++)
  543.         closedir(dirDir[i]);
  544.     }
  545.     else
  546.       eprintf("cannot open wadfile(s) or dir(s)!\n");
  547.   }
  548. }
  549.  
  550. //===========================================================================
  551.  
  552. /*
  553.  * ==================
  554.  * BeginBSPFile
  555.  * ==================
  556.  */
  557. void BeginBSPFile(__memBase)
  558. {
  559.   bspMem->availHeaders = 0;
  560.   AllocClusters(bspMem, (ALL_LUMPS | ALL_MAPS) & ~(LUMP_LIGHTING | LUMP_VISIBILITY));
  561.  
  562. // edge 0 is not used, because 0 can't be negated
  563.   bspMem->numedges = 1;
  564.  
  565. // leaf 0 is common solid with no faces
  566.   bspMem->numleafs = 1;
  567.   bspMem->dleafs[0].contents = CONTENTS_SOLID;
  568.  
  569.   firstface = 0;
  570. }
  571.  
  572. /*
  573.  * ==================
  574.  * FinishBSPFile
  575.  * ==================
  576.  */
  577. void FinishBSPFile(__memBase, FILE *bspFile)
  578. {
  579.   mprintf("----- FinishBSPFile -----\n");
  580.  
  581.   WriteMiptex(bspMem);
  582.   WriteBSP(bspFile, bspMem);
  583.   PrintClusters(bspMem, 0, TRUE);
  584. }
  585.